package sectorCrack.process;

import java.util.ArrayList;

import sectorCrack.bean.Dat;
import sectorCrack.bean.JobConfig;

public class SectorQCProcessor {

	ArrayList<Dat> sectorData;
	JobConfig jobConfig;

	public SectorQCProcessor() {

	}

	public SectorQCProcessor(ArrayList<Dat> sectorData, JobConfig jobConfig) {
		this.sectorData = sectorData;
		this.jobConfig = jobConfig;
	}

	public ArrayList<Dat> getSectorData() {
		return sectorData;
	}

	public void setSectorData(ArrayList<Dat> sectorData) {
		this.sectorData = sectorData;
	}

	public ArrayList<Dat> process() {
		for (Dat dat : sectorData) {
			if (dat.getSnr() <= jobConfig.getSnrThreshold()) {
				dat.setVelocityRaw(Float.NaN);
				dat.setVelocitySpikeFiltered(Float.NaN);
			}
		}
		fixVelocity(sectorData, 0);
		fixVelocity(sectorData, 1);

		return sectorData;
	}

	private float getVelocity(Dat d, int mode) {
		if (mode == 0) {
			return d.getVelocityRaw();
		}
		return d.getVelocitySpikeFiltered();
	}

	private void setVelocity(Dat d, float value, int mode) {
		if (mode == 0) {
			d.setVelocityRaw(value);
		} else {
			d.setVelocitySpikeFiltered(value);
		}
	}

	private void fixVelocity(ArrayList<Dat> datList, int mode) {
		float previousV = -999;
		float previousAz = -999;
		float previousEl = -999;
		float currentV = 0;
		for (Dat dat : datList) {
			if (previousAz == -999 || previousEl == -999) {
				previousAz = dat.getAzimuthMax();
				previousEl = dat.getElevationMax();
			}
			if (previousAz != dat.getAzimuthMax() || previousEl != dat.getElevationMax()) {
				previousV = -999;
			}
			currentV = getVelocity(dat, mode);
			previousAz = dat.getAzimuthMax();
			previousEl = dat.getElevationMax();
			if (Float.isNaN(currentV)) {
				previousV = -999;
				continue;
			}
			if (previousV == -999) {
				previousV = currentV;
			} else if (Math.abs(previousV - currentV) > jobConfig.getVelThreshold()) {
				setVelocity(dat, previousV * jobConfig.getPrevCoeff() + currentV * jobConfig.getCurrCoeff(), mode);
			} else {
				previousV = currentV;
			}
		}
		for (int i = 0; i < datList.size(); i++) {
			boolean prevNan = true;
			if (i - 1 < 0 || datList.get(i - 1).getAzimuthMax() != datList.get(i).getAzimuthMax() || datList.get(i - 1).getElevationMax() != datList.get(i).getElevationMax()) {
				prevNan = true;
			} else {
				prevNan = Float.isNaN(getVelocity(datList.get(i - 1), mode));
			}
			boolean nextNan = true;
			if (i + 1 >= datList.size() || datList.get(i + 1).getAzimuthMax() != datList.get(i).getAzimuthMax() || datList.get(i + 1).getElevationMax() != datList.get(i).getElevationMax()) {
				nextNan = true;
			} else {
				nextNan = Float.isNaN(getVelocity(datList.get(i + 1), mode));
			}
			if (prevNan && nextNan) {
				setVelocity(datList.get(i), Float.NaN, mode);
			}
		}

	}
}
